package server.app.fileupload;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.Callable;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
import common.BaseUtils;

public class SingleImgCompress implements Callable<String>
{
    File needCompressFile;
    double compressRate;
    double width = 160D;
    double height = 120D;
    String rebackFileName;

    File parentDirectory;

    SingleImgCompress(File parentDirectory, File file)
    {
        this.parentDirectory = parentDirectory;
        this.needCompressFile = file;
    }

    SingleImgCompress(File file)
    {
        this.needCompressFile = file;
        this.parentDirectory = file.getParentFile();
    }

    private void compressPic() throws IOException
    {
        if (!needCompressFile.exists())
        {
            rebackFileName = needCompressFile.getName();
            return;
        }
        // Read the image file.record the start time;
        Image img = ImageIO.read(needCompressFile);
        if (img.getWidth(null) == -1)
        {
            return;
        }
        // got the compress rate
        double rate = getCompressRate(img);
        // redefine the new image width and height

        double newWidth = (int) (((double) img.getWidth(null)) / rate);
        double newHeight = (int) (((double) img.getHeight(null)) / rate);
        // got the original image to bufferedImage
        BufferedImage tag = new BufferedImage((int) newWidth, (int) newHeight, BufferedImage.TYPE_INT_RGB);
        // got graphics
        Graphics gc = tag.getGraphics();
        // redraw the image and scaled this image with new width and height.
        // SCALE_FAST,SCALE_SMOOTH
        gc.drawImage(img.getScaledInstance((int) newWidth, (int) newHeight, Image.SCALE_SMOOTH), 0,
            0, null);
        // Create a new file for store the redrawed image;
        File file = new File(parentDirectory, getSmallPicName(needCompressFile.getName()));
        if (file.exists())
        {
            file.deleteOnExit();
            file.createNewFile();
        }
        FileOutputStream out = new FileOutputStream(file);
        // write to file
        ImageIO.write(tag, "jpeg", out);
        // destroy the references
        gc.dispose();
        out.flush();
        out.close();

        gc = null;
        out = null;
        needCompressFile = null;
        rebackFileName = null;
    }

    private double getCompressRate(Image img)
    {
        double rate1 = 0, rate2 = 0;
        if (getWidth() > 0)
        {
            rate1 = ((double) img.getWidth(null)) / (double) getWidth() + 0.1;
        }
        if (getHeight() > 0)
        {
            rate2 = ((double) img.getHeight(null)) / (double) getHeight() + 0.1;
        }
        double rate = Math.max(rate1, rate2);
        if (compressRate > 0)
        {
            rate = Math.max(rate, compressRate);
        }

        if (rate == 0)
        {
            rate = 1;
        }
        return rate;
    }

    private String getSmallPicName(String name)
    {
        String suffix = StringUtils.substringAfter(name, ".");
        String filename = StringUtils.substringBefore(name, ".");
        return BaseUtils.encodeForBase64(String.format("%s_%s", BaseUtils.decodeForBase64(filename), "small")) + "."
                        + suffix;
    }

    public double getCompressRate()
    {
        return compressRate;
    }

    public void setCompressRate(double compressRate)
    {
        this.compressRate = compressRate;
    }

    public double getWidth()
    {
        return width;
    }

    public void setWidth(double width)
    {
        this.width = width;
    }

    public double getHeight()
    {
        return height;
    }

    public void setHeight(double height)
    {
        this.height = height;
    }

    public String call() throws Exception
    {
        compressPic();
        return rebackFileName;
    }
}
